// ksun48
#include <bits/stdc++.h>
using namespace std;

namespace atcoder {

	namespace internal {
	
	#if __cplusplus >= 202002L
	
	using std::bit_ceil;
	
	#else
	
	// @return same with std::bit::bit_ceil
	unsigned int bit_ceil(unsigned int n) {
		unsigned int x = 1;
		while (x < (unsigned int)(n)) x *= 2;
		return x;
	}
	
	#endif
	
	// @param n `1 <= n`
	// @return same with std::bit::countr_zero
	int countr_zero(unsigned int n) {
	#ifdef _MSC_VER
		unsigned long index;
		_BitScanForward(&index, n);
		return index;
	#else
		return __builtin_ctz(n);
	#endif
	}
	
	// @param n `1 <= n`
	// @return same with std::bit::countr_zero
	constexpr int countr_zero_constexpr(unsigned int n) {
		int x = 0;
		while (!(n & (1 << x))) x++;
		return x;
	}
	
	}  // namespace internal
	
}  // namespace atcoder
	
namespace atcoder {

	#if __cplusplus >= 201703L
	
	template <class S, auto op, auto e> struct segtree {
		static_assert(std::is_convertible_v<decltype(op), std::function<S(S, S)>>,
					  "op must work as S(S, S)");
		static_assert(std::is_convertible_v<decltype(e), std::function<S()>>,
					  "e must work as S()");
	
	#else
	
	template <class S, S (*op)(S, S), S (*e)()> struct segtree {
	
	#endif
	
	  public:
		segtree() : segtree(0) {}
		explicit segtree(int n) : segtree(std::vector<S>(n, e())) {}
		explicit segtree(const std::vector<S>& v) : _n(int(v.size())) {
			size = (int)internal::bit_ceil((unsigned int)(_n));
			log = internal::countr_zero((unsigned int)size);
			d = std::vector<S>(2 * size, e());
			for (int i = 0; i < _n; i++) d[size + i] = v[i];
			for (int i = size - 1; i >= 1; i--) {
				update(i);
			}
		}
	
		void set(int p, S x) {
			assert(0 <= p && p < _n);
			p += size;
			d[p] = x;
			for (int i = 1; i <= log; i++) update(p >> i);
		}
	
		S get(int p) const {
			assert(0 <= p && p < _n);
			return d[p + size];
		}
	
		S prod(int l, int r) const {
			assert(0 <= l && l <= r && r <= _n);
			S sml = e(), smr = e();
			l += size;
			r += size;
	
			while (l < r) {
				if (l & 1) sml = op(sml, d[l++]);
				if (r & 1) smr = op(d[--r], smr);
				l >>= 1;
				r >>= 1;
			}
			return op(sml, smr);
		}
	
		S all_prod() const { return d[1]; }
	
		template <bool (*f)(S)> int max_right(int l) const {
			return max_right(l, [](S x) { return f(x); });
		}
		template <class F> int max_right(int l, F f) const {
			assert(0 <= l && l <= _n);
			assert(f(e()));
			if (l == _n) return _n;
			l += size;
			S sm = e();
			do {
				while (l % 2 == 0) l >>= 1;
				if (!f(op(sm, d[l]))) {
					while (l < size) {
						l = (2 * l);
						if (f(op(sm, d[l]))) {
							sm = op(sm, d[l]);
							l++;
						}
					}
					return l - size;
				}
				sm = op(sm, d[l]);
				l++;
			} while ((l & -l) != l);
			return _n;
		}
	
		template <bool (*f)(S)> int min_left(int r) const {
			return min_left(r, [](S x) { return f(x); });
		}
		template <class F> int min_left(int r, F f) const {
			assert(0 <= r && r <= _n);
			assert(f(e()));
			if (r == 0) return 0;
			r += size;
			S sm = e();
			do {
				r--;
				while (r > 1 && (r % 2)) r >>= 1;
				if (!f(op(d[r], sm))) {
					while (r < size) {
						r = (2 * r + 1);
						if (f(op(d[r], sm))) {
							sm = op(d[r], sm);
							r--;
						}
					}
					return r + 1 - size;
				}
				sm = op(d[r], sm);
			} while ((r & -r) != r);
			return 0;
		}
	
	  private:
		int _n, size, log;
		std::vector<S> d;
	
		void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
	};
	
}  // namespace atcoder


template <typename T> T mod_inv_in_range(T a, T m) {
	// assert(0 <= a && a < m);
	T x = a, y = m;
	// coeff of a in x and y
	T vx = 1, vy = 0;
	while (x) {
		T k = y / x;
		y %= x;
		vy -= k * vx;
		std::swap(x, y);
		std::swap(vx, vy);
	}
	assert(y == 1);
	return vy < 0 ? m + vy : vy;
}

template <typename T> struct extended_gcd_result {
	T gcd;
	T coeff_a, coeff_b;
};
template <typename T> extended_gcd_result<T> extended_gcd(T a, T b) {
	T x = a, y = b;
	// coeff of a and b in x and y
	T ax = 1, ay = 0;
	T bx = 0, by = 1;
	while (x) {
		T k = y / x;
		y %= x;
		ay -= k * ax;
		by -= k * bx;
		std::swap(x, y);
		std::swap(ax, ay);
		std::swap(bx, by);
	}
	return {y, ay, by};
}

template <typename T> T mod_inv(T a, T m) {
	a %= m;
	a = a < 0 ? a + m : a;
	return mod_inv_in_range(a, m);
}

template <int MOD_> struct modnum {
	static constexpr int MOD = MOD_;
	static_assert(MOD_ > 0, "MOD must be positive");

private:
	int v;

public:

	modnum() : v(0) {}
	modnum(int64_t v_) : v(int(v_ % MOD)) { if (v < 0) v += MOD; }
	explicit operator int() const { return v; }
	friend std::ostream& operator << (std::ostream& out, const modnum& n) { return out << int(n); }
	friend std::istream& operator >> (std::istream& in, modnum& n) { int64_t v_; in >> v_; n = modnum(v_); return in; }

	friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
	friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }

	modnum inv() const {
		modnum res;
		res.v = mod_inv_in_range(v, MOD);
		return res;
	}
	friend modnum inv(const modnum& m) { return m.inv(); }
	modnum neg() const {
		modnum res;
		res.v = v ? MOD-v : 0;
		return res;
	}
	friend modnum neg(const modnum& m) { return m.neg(); }

	modnum operator- () const {
		return neg();
	}
	modnum operator+ () const {
		return modnum(*this);
	}

	modnum& operator ++ () {
		v ++;
		if (v == MOD) v = 0;
		return *this;
	}
	modnum& operator -- () {
		if (v == 0) v = MOD;
		v --;
		return *this;
	}
	modnum& operator += (const modnum& o) {
		v -= MOD-o.v;
		v = (v < 0) ? v + MOD : v;
		return *this;
	}
	modnum& operator -= (const modnum& o) {
		v -= o.v;
		v = (v < 0) ? v + MOD : v;
		return *this;
	}
	modnum& operator *= (const modnum& o) {
		v = int(int64_t(v) * int64_t(o.v) % MOD);
		return *this;
	}
	modnum& operator /= (const modnum& o) {
		return *this *= o.inv();
	}

	friend modnum operator ++ (modnum& a, int) { modnum r = a; ++a; return r; }
	friend modnum operator -- (modnum& a, int) { modnum r = a; --a; return r; }
	friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
	friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
	friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }
	friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= b; }
};

using num = modnum<998244353>;
	
struct st {
	int cnt;
	num v[2][2];
};

st op(st x, st y){
	if(!x.cnt) return y;
	if(!y.cnt) return x;
	st res;
	res.cnt = x.cnt + y.cnt;
	for(int a = 0; a < 2; a++){
		for(int b = 0; b < 2; b++){
			res.v[a][b] = 0;
		}
	}
	for(int a = 0; a < 2; a++){
		for(int b = 0; b < 2; b++){
			for(int c = 0; c < 2; c++){
				if(b+c == 0) continue;
				for(int d = 0; d < 2; d++){
					res.v[a][d] += x.v[a][b] * y.v[c][d];
				}
			}
		}
	}
	return res;
}

st e(){
	st z;
	z.cnt = 0;
	return z;
}


vector<num> fact, ifact;

void init(){
	int N = 4.1e5;
	fact.resize(N);
	fact[0] = 1;
	for(int i = 1; i < N; i++) fact[i] = i * fact[i-1];
	ifact.resize(N);
	ifact.back() = 1 / fact.back();
	for(int i = N - 1; i > 0; i--) ifact[i-1] = i * ifact[i];
}

num ncr(int n, int k){
	if(k < 0 || k > n) return 0;
	return fact[n] * ifact[k] * ifact[n-k];
}

int main(){
	ios_base::sync_with_stdio(false), cin.tie(nullptr);
	init();
	int N, Q;
	cin >> N >> Q;
	vector<int> A(N, -1);
	atcoder::segtree<st, op, e> seg(N);
	set<int> d;
	d.insert(-1);
	d.insert(N);
	auto get_st = [&](int len, int val) -> st {
		st cur;
		cur.cnt = len;
		for(int i = 0; i < 2; i++){
			for(int j = 0; j < 2; j++){
				cur.v[i][j] = 0;
			}
		}
		if(val <= len){
			if(len == 1){
				cur.v[val][val] = 1;
			} else if(len == 2){
				for(int i = 0; i < 2; i++){
					for(int j = 0; j < 2; j++){
						if(i+j == val && val > 0){
							cur.v[i][j] = 1;
						}
					}
				}
			} else if(len == 3){
				for(int i = 0; i < 2; i++){
					for(int j = 0; j < 2; j++){
						for(int k = 0; k < 2; k++){
							if(i+j+k == val && i+j > 0 && j+k > 0){
								cur.v[i][k] += 1;
							}
						}
					}
				}
			} else {
				for(int i = 0; i < 2; i++){
					for(int j = 0; j < 2; j++){
						int nlen = len - int(i == 0) - int(j == 0);
						if(val <= nlen){
							int sp = nlen-val;
							cur.v[i][j] += ncr(nlen-sp-1, sp);
						}
					}
				}
			}
		}
		return cur;
	};
	vector<num> ways_0(N+1), ways_1(N+1);
	ways_0[0] = ways_1[0] = 1;
	for(int i = 1; i <= N; i++){
		ways_1[i] = ways_1[i-1] + ways_0[i-1];
		ways_0[i] = ways_1[i-1];
	}
	for(int q = 0; q < Q; q++){
		int x, y;
		cin >> x >> y;
		x--;
		if(y != -1){
			y = (x+1)-y;
		}
		if(A[x] != -1){
			A[x] = -1;
			seg.set(x, e());
			d.erase(x);
			auto it = d.lower_bound(x);
			int nx = *it;
			int px = *prev(it);
			if(nx < N){
				int len = nx-px;
				int val = A[nx] - (px == -1 ? 0 : A[px]);
				seg.set(nx, get_st(len, val));
			}
		}
		if(y != -1){
			A[x] = y;
			d.insert(x);
			auto it = d.find(x);
			int nx = *next(it);
			int px = *prev(it);
			{
				int len = x-px;
				int val = A[x] - (px == -1 ? 0 : A[px]);
				seg.set(x, get_st(len, val));
			}
			if(nx < N){
				int len = nx-x;
				int val = A[nx] - (x == -1 ? 0 : A[x]);
				seg.set(nx, get_st(len, val));
			}
		}
		st res = seg.all_prod();
		num ans = 0;
		if(res.cnt == 0){
			ans += ways_1[N];
		} else {
			int v = N-res.cnt;
			for(int i = 0; i < 2; i++){
				for(int j = 0; j < 2; j++){
					ans += res.v[i][j] * (j ? ways_1 : ways_0)[v];
				}
			}
		}
		cout << ans << '\n';
	}
}
